﻿using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace OpenCVDemo.Tool
{
    public partial class Form1 : Form
    {
        private string[] files = Directory.GetFiles("./images/", "*.jpg*"); //文件夹下所有jpg文件
        private int imgIndex = 0;
        private Mat img2;

        private VideoCapture cap = new VideoCapture();
        private Mat frame = new Mat();

        private VideoCapture cap2 = new VideoCapture();
        private Mat frame2 = new Mat();
        private Mat gray2 = new Mat();

        public Mat img3 = new Mat();
        public Mat temp = new Mat();
        public Mat result = new Mat();
        public Point ptStart = new Point();
        public bool isMouseDown = false;

        public Mat img4 = new Mat();
        public Mat temp4 = new Mat();
        public Mat result4 = new Mat();
        public Point ptStart4 = new Point();
        public bool isMouseDown4 = false;

        public Mat img5 = new Mat();

        public Mat frame6 = new Mat();
        public VideoCapture cap6 = new VideoCapture();
        public int framePos6;

        public Form1()
        {
            InitializeComponent();

            #region 初始化
            //初始化
            Mat img = CvInvoke.Imread(files[0]);
            pictureBox1.Image = img.ToBitmap();

            img2 = CvInvoke.Imread("./images/47.jpg");
            pictureBox2.Image = img2.ToBitmap(); 
            #endregion
        }

        private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        #region 图片浏览器
        /// <summary>
        /// 图片浏览器-上一张
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            if (imgIndex == 0)
            {
                MessageBox.Show("已经是第一张！");
            }
            else
            {
                imgIndex--;
                Mat img = CvInvoke.Imread(files[imgIndex]);
                pictureBox1.Image = img.ToBitmap();
            }
        }

        /// <summary>
        /// 图片浏览器-下一张
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            if (imgIndex == files.Length - 1)
            {
                MessageBox.Show("已经是最后一张！");
            }
            else
            {
                imgIndex++;
                Mat img = CvInvoke.Imread(files[imgIndex]);
                pictureBox1.Image = img.ToBitmap();
            }
        }
        #endregion

        #region 图片颜色空间
        /// <summary>
        /// 图片颜色空间-RGB
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click(object sender, EventArgs e)
        {
            Mat rgbImg = new Mat();
            CvInvoke.CvtColor(img2, rgbImg, ColorConversion.Bgr2Rgb);
            pictureBox3.Image = rgbImg.ToBitmap();
        }

        /// <summary>
        /// 图片颜色空间-HSV
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button4_Click(object sender, EventArgs e)
        {
            Mat hsvImg = new Mat();
            CvInvoke.CvtColor(img2, hsvImg, ColorConversion.Bgr2Hsv);
            pictureBox3.Image = hsvImg.ToBitmap();
        }

        /// <summary>
        /// 图片颜色空间-Lab
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button5_Click(object sender, EventArgs e)
        {
            Mat labImg = new Mat();
            CvInvoke.CvtColor(img2, labImg, ColorConversion.Bgr2Lab);
            pictureBox3.Image = labImg.ToBitmap();
        }
        #endregion

        #region 视频播放
        /// <summary>
        /// 视频播放-开始
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button6_Click(object sender, EventArgs e)
        {
            cap = new VideoCapture("./images/0.avi");
            if (cap.IsOpened) //判断如果视频打开成功，则开启timer1
            {
                timer1.Start(); //开启timer1
            }
        }

        /// <summary>
        /// 视频播放-关闭
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button7_Click(object sender, EventArgs e)
        {
            timer1.Stop();
            cap.Stop();
            pictureBox4.Image = null;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            frame = cap.QueryFrame(); //获取摄像头帧
            if (frame != null) //判断如果当前帧不为空
            {
                pictureBox4.Image = frame.ToBitmap();
            }
        }
        #endregion

        #region 视频处理
        /// <summary>
        /// 视频处理-播放视频
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button9_Click(object sender, EventArgs e)
        {
            cap2 = new VideoCapture("./images/0.avi");
            if (cap2.IsOpened) //判断如果视频打开成功，则开启timer1
            {
                timer2.Start(); //开启timer1
            }
        }

        /// <summary>
        /// 视频处理-关闭视频
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button8_Click(object sender, EventArgs e)
        {
            timer2.Stop();
            cap2.Stop();

            pictureBox5.Image = null;
            pictureBox6.Image = null;
        }

        private void timer2_Tick(object sender, EventArgs e)
        {
            frame2 = cap2.QueryFrame(); //获取摄像头帧
            if (frame2 != null) //判断如果当前帧不为空
            {
                pictureBox5.Image = frame2.ToBitmap();
                CvInvoke.CvtColor(frame2, gray2, ColorConversion.Bgr2Gray);
                CvInvoke.Canny(gray2, gray2, 30, 250);//Canny边缘检测
                pictureBox6.Image = gray2.ToBitmap();
            }
        }
        #endregion

        #region 鼠标矫正图像
        /// <summary>
        /// 鼠标矫正图像-加载图片
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button10_Click(object sender, EventArgs e)
        {
            img3 = CvInvoke.Imread("./images/qrcode.jpg");
            pictureBox7.Image = img3.ToBitmap();
            pictureBox8.Image = null;

            //备份原图
            temp = img3.Clone();
            result = img3.Clone();
        }

        private void pictureBox7_MouseDown(object sender, MouseEventArgs e)
        {
            //鼠标按下的时候获取起始坐标
            isMouseDown = true;
            double xZoomRate = img3.Cols / (double)pictureBox7.Width;
            double yZoomRate = img3.Rows / (double)pictureBox7.Height;
            ptStart = new Point((int)(e.X * xZoomRate), (int)(e.Y * yZoomRate));
        }

        private void pictureBox7_MouseMove(object sender, MouseEventArgs e)
        {
            //根据起始坐标和结束坐标绘制直线
            if (isMouseDown)
            {
                temp.CopyTo(img3);//重置
                double xZoomRate = img3.Cols / (double)pictureBox7.Width;
                double yZoomRate = img3.Rows / (double)pictureBox7.Height;
                Point ptEnd = new Point((int)(e.X * xZoomRate), (int)(e.Y * yZoomRate));
                CvInvoke.Line(img3, ptStart, ptEnd, new MCvScalar(0, 255, 0), 2);
                pictureBox7.Image = img3.ToBitmap();
            }
        }

        private void pictureBox7_MouseUp(object sender, MouseEventArgs e)
        {
            //根据起始坐标和结束坐标绘制直线
            //图像旋转
            result = temp.Clone();
            isMouseDown = false;
            double xZoomRate = img3.Cols / (double)pictureBox7.Width;
            double yZoomRate = img3.Rows / (double)pictureBox7.Height;
            Point ptEnd = new Point((int)(e.X * xZoomRate), (int)(e.Y * yZoomRate));
            CvInvoke.Line(img3, ptStart, ptEnd, new MCvScalar(0, 255, 0), 2);

            double angle = Math.Atan2((ptEnd.Y - ptStart.Y), (ptEnd.X - ptStart.X)) * 180 / Math.PI;
            Mat roateM = new Mat();
            Point center = new Point(result.Cols / 2, result.Cols / 2);
            CvInvoke.GetRotationMatrix2D(center, angle, 1, roateM);
            CvInvoke.WarpAffine(result, result, roateM, result.Size);
            pictureBox8.Image = result.ToBitmap();
            MessageBox.Show(Convert.ToString(angle));
        }
        #endregion

        #region 鼠标截取ROI
        /// <summary>
        /// 鼠标截取ROI
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button11_Click(object sender, EventArgs e)
        {
            //加载显示图片并备份原图
            img4 = CvInvoke.Imread("./images/7.jpg");
            pictureBox9.Image = img4.ToBitmap();
            pictureBox10.Image = null;

            temp4 = img4.Clone();
        }

        private void pictureBox9_MouseDown(object sender, MouseEventArgs e)
        {
            //获取起始坐标
            isMouseDown4 = true;
            double xZoomRate = img4.Cols / (double)pictureBox9.Width;
            double yZoomRate = img4.Rows / (double)pictureBox9.Height;
            ptStart4 = new Point((int)(e.X * xZoomRate), (int)(e.Y * yZoomRate));
        }

        private void pictureBox9_MouseMove(object sender, MouseEventArgs e)
        {
            //获取ROI区域
            if (isMouseDown4)
            {
                temp4.CopyTo(img4);//重置
                double xZoomRate = img4.Cols / (double)pictureBox9.Width;
                double yZoomRate = img4.Rows / (double)pictureBox9.Height;
                Point ptEnd4 = new Point((int)(e.X * xZoomRate), (int)(e.Y * yZoomRate));
                CvInvoke.Rectangle(img4, new Rectangle(ptStart4, new Size(ptEnd4.X - ptStart4.X, ptEnd4.Y - ptStart4.Y)), new MCvScalar(0, 255, 0), 2);
                result4 = new Mat(temp4, new Rectangle(ptStart4, new Size(ptEnd4.X - ptStart4.X, ptEnd4.Y - ptStart4.Y)));
                pictureBox9.Image = img4.ToBitmap();
            }
        }

        private void pictureBox9_MouseUp(object sender, MouseEventArgs e)
        {
            //截取并保存
            isMouseDown4 = false;
            pictureBox10.Image = result4.ToBitmap();
            CvInvoke.Imwrite("roi.bmp", result4);
        }


        #endregion

        #region 二值化阈值
        /// <summary>
        /// 二值化阈值-加载图片
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button12_Click(object sender, EventArgs e)
        {
            img5 = CvInvoke.Imread("./images/102.png");
            pictureBox11.Image = img5.ToBitmap();
            pictureBox12.Image = null;
            trackBar1.Value = 0;
        }

        private void trackBar1_ValueChanged(object sender, EventArgs e)
        {
            label3.Text = trackBar1.Value.ToString();
            Mat grayImg = new Mat();
            CvInvoke.CvtColor(img5, grayImg, ColorConversion.Bgr2Gray);
            CvInvoke.Threshold(grayImg, grayImg, trackBar1.Value, 255, ThresholdType.BinaryInv);
            pictureBox12.Image = grayImg.ToBitmap();
        }
        #endregion

        #region 视频播放器
        /// <summary>
        /// 打开视频
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button13_Click(object sender, EventArgs e)
        {
            cap6 = new VideoCapture("./images/0.avi");
            int frameCount = (int)cap6.Get(CapProp.FrameCount);
            trackBar2.Maximum = frameCount;
            timer3.Start();
        }

        /// <summary>
        /// 播放
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button14_Click(object sender, EventArgs e)
        {
            timer3.Start();
        }

        /// <summary>
        /// 暂停
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button15_Click(object sender, EventArgs e)
        {
            timer3.Stop();
        }

        private void timer3_Tick(object sender, EventArgs e)
        {
            frame6 = cap6.QueryFrame();
            if (frame6 == null)
            {
                return;
            }
            trackBar2.Value = (int)cap6.Get(CapProp.PosFrames);
            pictureBox13.Image = frame6.ToBitmap();
        }

        private void trackBar2_ValueChanged(object sender, EventArgs e)
        {
            cap6.Set(CapProp.PosFrames, trackBar2.Value);
        } 
        #endregion
    }
}
